//
//  ZCCreateQRCode.m
//  ZhiChe-Wms
//
//  Created by 高睿婕 on 2018/8/23.
//  Copyright © 2018年 Regina. All rights reserved.
//

#import "ZCCreateQRCode.h"

@implementation ZCCreateQRCode

+ (UIImage *)createQRCodeFromString:(NSString *)string codeSize:(CGFloat)codesize {
    
    codesize = [self validateCodeSize:codesize];
    
    //create a QRCodeImage
    CIImage *originImage = [self createQRCode:string];
    //progress QRCodeImage
    UIImage *progressImage = [self excludeFuzzyImageFromCIImage:originImage size:codesize];
    
    UIImage *effectiveImage = [self imageFillBlackColorAndTransparent:progressImage
                                                                red:0
                                                              green:0
                                                               blue:0];
    return effectiveImage;
//    return progressImage;
    
}

#pragma mark-private
/**
 *  control the codeSize to fit
 *
 *  @param codeSize Size
 *
 *  @return fit size
 */
+ (CGFloat)validateCodeSize:(CGFloat)codeSize {
    //Max
    codeSize = MAX(160, codeSize);
    //Min
    codeSize = MIN(CGRectGetWidth([UIScreen mainScreen].bounds)-80, codeSize);
    
    return codeSize;
}

/**
 *  Use CIFilter Create a QRCodeImage
 *
 *  @param string String
 *
 *  @return CIImage
 */
+ (CIImage *)createQRCode:(NSString *)string {
    NSData *dataString = [string dataUsingEncoding:NSUTF8StringEncoding];
    //创建滤镜
    CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
    //设置数据KVC
    [filter setValue:dataString forKey:@"inputMessage"];
    //设置纠错级别
    [filter setValue:@"H" forKey:@"inputCorrectionLevel"];
    //输出CIImage
    return filter.outputImage;
}

/**
 *  progress CIImage
 *
 *  @param image CIImage
 *  @param size  Size
 *
 *  @return UIImage
 */
+ (UIImage *)excludeFuzzyImageFromCIImage:(CIImage *)image size:(CGFloat)size {
    //返回一个整数大小的尺寸
    CGRect extent = CGRectIntegral(image.extent);
    //缩放比例
    CGFloat scale = MIN(size/CGRectGetWidth(extent), size/CGRectGetHeight(extent));
    
    //size_t类型返回缩放比例之后的尺寸
    size_t width = CGRectGetWidth(extent)*scale;
    size_t height = CGRectGetHeight(extent)*scale;
    
    
    //使用RGB颜色空间
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
    
    //创建一个bitmap上下文
    CGContextRef bitmapRef = CGBitmapContextCreate(nil, width, height, 8, 0, colorSpace,(CGBitmapInfo)kCGImageAlphaNone);
    //CIContext图形上下文
    CIContext *context = [CIContext contextWithOptions:nil];
    //创建一个extent大小的CGImageRef
    CGImageRef bitmapImage = [context createCGImage:image fromRect:extent];
    //生成图片的质量
    CGContextSetInterpolationQuality(bitmapRef, kCGInterpolationNone);
    //缩放
    CGContextScaleCTM(bitmapRef, scale, scale);
    //画图
    CGContextDrawImage(bitmapRef, extent, bitmapImage);
    //生成一张缩放后的bitmap图片
    CGImageRef scaleImage = CGBitmapContextCreateImage(bitmapRef);
    
    //释放内存
    CGContextRelease(bitmapRef);
    CGImageRelease(bitmapImage);
    CGColorSpaceRelease(colorSpace);
    
    return [UIImage imageWithCGImage:scaleImage];
}


/**
 *  Fill Color And Transparent BackGround
 *
 *  @param image Image
 *  @param red   R
 *  @param green G
 *  @param blue  B
 *
 *  @return UIImage
 */
+ (UIImage *)imageFillBlackColorAndTransparent:(UIImage *)image red:(NSUInteger)red green:(NSUInteger)green blue:(NSUInteger)blue {
    //图片的大小
    const int imageWidth = image.size.width;
    const int imageHeight = image.size.height;
    
    size_t bytesPerRow = imageWidth*4;
    //缓存大小
    uint32_t *rgbImageBuf = (uint32_t *)malloc(bytesPerRow * imageHeight);
    
    //使用RGB颜色空间
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(rgbImageBuf, imageWidth, imageHeight, 8, bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipLast);
    
    //绘制图像
    CGContextDrawImage(context, (CGRect){(CGPointZero),(image.size)},image.CGImage);
    unsigned char *data = CGBitmapContextGetData(context);
    
    UIImage *resultImage = [self fillWhiteWithImage:image imgPixel:data];
    
//    //像素的个数
//    int pixelNumber = imageWidth * imageHeight;
//
//    //遍历像素
//    [self fillWhiteToTransparentOnPixel:rgbImageBuf pixelNum:pixelNumber red:red green:green blue:blue];
//
//    //释放内存的数据
//    CGDataProviderRef dataProvider=CGDataProviderCreateWithData(NULL, rgbImageBuf, bytesPerRow,ProviderReleaseData);
//    //创建一张图片
//    CGImageRef imageRef = CGImageCreate(imageWidth, imageHeight, 8, 32, bytesPerRow, colorSpace, kCGImageAlphaLast | kCGBitmapByteOrder32Little, dataProvider,NULL, true, kCGRenderingIntentDefault);
//
//    //转换成UIImage图片
//    UIImage *resultImage = [UIImage imageWithCGImage:imageRef];
//
//    //释放内存
//    CGImageRelease(imageRef);
//    CGColorSpaceRelease(colorSpace);
//    CGContextRelease(context);
    
    return resultImage;
}


/**
 *  Fill Color Pixel And Transparent BackGround
 *
 *  @param rgbImageBuf Buffer
 *  @param pixelNum    Number
 *  @param red         R
 *  @param green       G
 *  @param blue        B
 */
+ (void)fillWhiteToTransparentOnPixel:(uint32_t *)rgbImageBuf pixelNum:(int)pixelNum red:(NSUInteger)red green:(NSUInteger)green blue:(NSUInteger)blue {
    //指针指向缓存区域的地址
    uint32_t *pCurPtr = rgbImageBuf;
    //遍历
    for (int i = 0; i < pixelNum; i++,pCurPtr++) {
        if ((*pCurPtr & 0xffffff00) < 0x99999900) {
            //指针指向指针的地址
            uint8_t *ptr = (uint8_t *)pCurPtr;
            ptr[3] = red;
            ptr[2] = green;
            ptr[1] = blue;
        }else {
            uint8_t *ptr = (uint8_t *)pCurPtr;
            //透明颜色
            ptr[0] = 0;
        }
    }
}


/**
 *  free Buffer
 *
 *  @param info info
 *  @param data data
 *  @param size size_t
 */
void ProviderReleaseData(void * info, const void * data, size_t size) {
    //释放内存数据
    free((void *)data);
}

+ (UIImage *)fillWhiteWithImage:(UIImage *)inImage imgPixel:(unsigned char *)imgPixel {
    CGImageRef inImageRef = [inImage CGImage];
    long w = CGImageGetWidth(inImageRef);
    long h = CGImageGetHeight(inImageRef);
    
    int wOff = 0;
    int pixOff = 0;
    
    /*        遍历修改位图像素值         */
    for (long y = 0; y<h; y++) {
        pixOff = wOff;
        for (long x = 0; x<w; x++) {
            int red = (unsigned char)imgPixel[pixOff];
            int green = (unsigned char)imgPixel[pixOff + 1];
            int blue = (unsigned char)imgPixel[pixOff + 2];
            int alpha = (unsigned char)imgPixel[pixOff + 3];
            float p[20];
            for (int i = 0; i < 20; i++) {
                if (i == 2 || i ==7 || i == 12) {
                    p[i] = 1.0f;
                }else {
                    p[i] = 0.0f;
                }
            }
            changeRGB(&red, &green, &blue, &alpha, p);
            imgPixel[pixOff] = red;
            imgPixel[pixOff + 1] = green;
            imgPixel[pixOff + 2] = blue;
            imgPixel[pixOff + 3] = alpha;
            pixOff += 4;
        }
        wOff += w * 4 ;
    }
    
    NSInteger dataLength = w * h * 4;
    //创建要输出的图像的相关参数
    CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, imgPixel, dataLength, NULL);
    
    if (!provider) {
        NSLog(@"创建输出图像相关参数失败！");
    }else{
        int bitsPerComponent = 8;
        int bitsPerPixel = 32;
        ItemCount bytesPerRow = 4 * w;
        CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
        CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
        CGColorRenderingIntent rederingIntent = kCGRenderingIntentDefault;
        //创建要输出的图像
        CGImageRef imageRef = CGImageCreate(w, h,bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider,NULL, YES, rederingIntent);
        if (!imageRef) {
            NSLog(@"创建输出图像失败");
        }else{
            UIImage *my_image = [UIImage imageWithCGImage:imageRef];
            CFRelease(imageRef);
            CGColorSpaceRelease(colorSpaceRef);
            CGDataProviderRelease(provider);
            
            
            NSData *data = UIImageJPEGRepresentation(my_image, 1.0);
            
            return [UIImage imageWithData:data];
        }
        
    }
    
    return nil;
}


static void changeRGB(int *red,int* green,int*blue,int*alpha ,const float *f){
    
    int redV = *red;
    int greenV = *green;
    int blueV = *blue;
    int alphaV = *alpha;
    *red = f[0] * redV + f[1]*greenV + f[2]*blueV + f[3] * alphaV + f[4];
    *green = f[5] * redV + f[6]*greenV + f[7]*blueV + f[8] * alphaV+ f[9];
    *blue = f[10] * redV + f[11]*greenV + f[12]*blueV + f[11] * alphaV+ f[14];
    *alpha = f[15] * redV + f[16]*greenV + f[17]*blueV + f[18] * alphaV+ f[19];
    
    *red < 0 ? (*red = 0):(0);
    *red > 255 ? (*red = 255):(0);
    
    *green < 0 ? (*green = 0):(0);
    *green > 255 ? (*green = 255):(0);
    
    *blue < 0 ? (*blue = 0):(0);
    *blue > 255 ? (*blue = 255):(0);
    
    
    *alpha < 0 ? (*alpha = 0):(0);
    *alpha > 255 ? (*alpha = 255):(0);
    
    
}

@end
